//
//  CHSInterviewQListController.m
//  ZXAnimationUtil_Example
//
//  Created by 朱新明 on 2023/9/13.
//  Copyright © 2023 simon. All rights reserved.
//

#import "CHSInterviewQListController.h"
#import <ZXCategoriesUtil/CAICategories.h>
#import <Masonry/Masonry.h>
#import "CHSInterviewAnController.h"

@interface CHSInterviewQListController ()<UITableViewDataSource,UITableViewDelegate>
@property (nonatomic, strong) UITableView *tableView;
@property (nonatomic, strong) NSMutableArray *dataMArray;

@end

@implementation CHSInterviewQListController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    [self setUI];
    [self setData];
}

- (void)setUI
{
    self.navigationItem.title = @"面试题";
    self.view.backgroundColor = [UIColor zx_colorWithHexString:@"#FDFEFF"];
    
    [self.view addSubview:self.tableView];
    [self.tableView mas_makeConstraints:^(MASConstraintMaker *make) {
        make.left.mas_equalTo(self.view.mas_left).with.offset(15);
        make.centerX.mas_equalTo(self.view.mas_centerX);
        make.top.equalTo(self.view.mas_top).with.offset(0);
        make.bottom.equalTo(self.view.mas_bottom);
    }];
//    if (@available(iOS 15.0, *)) {
//        self.tableView.sectionHeaderTopPadding = 0;
//    } else {
//        // Fallback on earlier versions
//    }
}


#pragma mark - Data

- (void)setData
{
    NSArray *arr = @[
        @{@"1":@"1.CADisplayLink与NSTimer的区别？【RunLoop】【动画】"},
        @{@"2":@"2. UIView与CALayer有什么区别？【图层和视图之间的关系】"},
        @{@"3":@"3.隐式动画与显式动画有什么区别？"},
        @{@"3-2":@"3-2.核心动画和UIView的animation类方法创建的动画有什么区别？"},
        @{@"4":@"4.核心动画绘制内容过程？【图层为绘图和动画提供了基础】"},
        @{@"5":@"5.图层的绘图与基于视图的绘图有什么区别？【图层为绘图和动画提供了基础】"},
        @{@"6":@"6.模型层、表现层、渲染层的概念和区别？【图层树反映了动画状态的不同方面】"},

    ];
    self.dataMArray = [NSMutableArray arrayWithArray:arr];
    //    self.dataMArray = [NSMutableArray array];
    [self requestData];
}

- (void)requestData
{
    
}


#pragma mark -

- (UITableView *)tableView
{
    if (!_tableView)
    {
        UITableView *view = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStyleGrouped];
        view.backgroundColor = self.view.backgroundColor;
        view.delegate = self;
        view.dataSource = self;
        view.showsVerticalScrollIndicator = NO;
        [view registerClass:[UITableViewCell class] forCellReuseIdentifier:@"Cell"];
        view.estimatedRowHeight = 87;
        view.rowHeight = UITableViewAutomaticDimension;
        _tableView = view;
    }
    return _tableView;
}



- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    return 1;
}

- (NSInteger)tableView:(nonnull UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return self.dataMArray.count;
}


- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
    //    CHSMyRedpacketTableCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];
    //    [cell setData:nil];
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];
    NSDictionary *dic = [self.dataMArray objectAtIndex:indexPath.row];
    NSString *value = [dic.allValues firstObject];
    cell.textLabel.text = value;
    cell.textLabel.numberOfLines = 0;
    return cell;
}

- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
    if (section == 0) {
        return 0;
    }
    return 0.1;
}

- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section
{
    return 12;
}
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
    return [UIView new];
}
- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section
{
    return [UIView new];
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
    [tableView deselectRowAtIndexPath:indexPath animated:YES];
    NSDictionary *dic = [self.dataMArray objectAtIndex:indexPath.row];
    NSString *key = [dic.allKeys firstObject];
    NSString *value = [dic objectForKey:key];

    CHSInterviewAnController *vc = [CHSInterviewAnController new];
    NSMutableDictionary *anDic = [NSMutableDictionary dictionaryWithDictionary:@{@"title":value}];
    NSString *answer = nil;
    if ([key isEqualToString:@"1"]) {
        answer = @"相同点：\n（1）CADisplayLink和NSTimer都是一个计时器类；\n（2）CADisplayLink和NSTimer的对象都受RunLoop管理。（CADisplayLink和NSTimer的对象都需要以指定模式添加到runloop，才能周期性地调用selector；RunLoop强引用计时器，计时器强引用target）\n（3）CADisplayLink和NSTimer的对象都需要执行invalidate操作，才能从runloop移除，停止周期性地调用selector。\n（4）都不是一种实时机制。如果计时器的触发时间发生在长运行循环调用期间，或者当runloop(运行循环)处于不监视计时器的模式时，计时器将不会触发。不同点：\n（1）原理不同：\nCADisplayLink：是一个将渲染和屏幕显示的刷新率（刷新频率）同步的计时器类，和屏幕刷新频率绑定。每当屏幕内容刷新时，runloop就会向target发送一次selector消息。\nNSTimer：每当设定的周期时间到达后，runloop就会向target发送一次selector消息。\n（2）时间周期设置方式不同\nCADisplayLink：通过帧速率属性设置，间接得到回调间隔时间周期；\nNSTimer：在初始化时直接设定。\n（3）使用场合不同\nCADisplayLink：因为和屏幕的刷新频率同步，所以更适合用于UI有关的重绘和手动的动画效果。这样即使遇到掉帧的情况，渲染和动画显示的时间周期也不受影响。\nNSTimer的使用范围要广泛的多。\n比如：MBProgressHUD中，使用CADisplayLink 来获取NSProgress进度值，然后刷新UI进度渲染；而那些最小显示时间设置就是用NSTimer定时器来处理；\n（4）除此之外，CADisplayLink的触发方法在回调时，还可以获取距离上次调用的时间间隔（屏幕两次刷新的间隔时间），可以帮助开发者更好地掌控程序的帧率。\n文档引用：《Performance and metrics》-响应-1-提高响应速度（页面卡顿-Improving app responsiveness）\n使用CADisplayLink或CVDisplayLink来确保在垂直同步发生时开始下一帧的工作，而不是在垂直同步间隔的中间开始，从而最大限度地提高渲染时间。";
    }
    if ([key isEqualToString:@"2"]) {
     
        answer = @"答：\n（1）UIView实际上是封装了显示与交互功能的上层组件，其显示部分实际是由内部的图层负责的。\n（2）在iOS中每个view都有一个关联的layer对象。\n（3）view只是对layer对象的包装。\n（4）view负责交互，图层负责管理和操作view的视觉内容。图层的初始层次结构对应相应的视图层次结构，对视图添加移除操作的时候，会保持图层与视图同步。\n（5）View和CALayer都管理内容的视觉几何。通过bounds和positon定义大小和位置。\n区别：\n（1）UIView负责响应事件，CALayer不负责。\n（2）图层的属性修改会触发隐式动画。\n（3）图层还具有视图所没有的其他属性，例如锚点anchor，锚点定义了操作发生的点。\n（4）可以在图层层次结构中加入与view不关联的图层。\n文档引用：\n官方文档-《Core Animation Programming Guide》-1\n1)这个基础结构的核心是layer（图层）对象，您可以使用它来管理和操作内容。\n2)图层可以组织成层次结构。图层的层次结构反映了相应的视图层次结构。你还可以将独立的图层添加到图层层次结构中，以扩展应用程序的视觉内容。\n官方文档-《Core Animation Programming Guide》-2-Core Animation Basics-图层和视图之间的关系\n1)你不能仅仅基于图层对象创建一个可视界面。图层为视图提供基础结构。\n2)图层不处理事件、绘制内容、参与响应链或做许多其他事情。\n3)每个视图都有相应的图层对象支持；\n4)视图只是层对象的薄包装；\na、UIView的继承结构为: UIResponder : NSObject。\nb、CALayer的继承结构为：NSObject。（直接从 NSObject继承，因为缺少了UIResponder类，所以CALayer不能响应任何用户事件。） \n<官方文档-《Core Animation Programming Guide》-3〉\n图层管理应用程序的视觉内容，并提供修改该内容的样式和视觉外观的选项。";
    }
    if ([key isEqualToString:@"3"]) {

        answer = @"答：\n(1)隐式动画：改变图层的某个可动画属性时，会（使用默认的动画属性）产生动画效果。大部分使用默认隐含的CABasicAnimation对象实现动画，小部分会使用默认的隐含CATransition对象实现动画。\n(2)显式动画：需要自己使用动画对象来产生动画效果。只产生动画，不修改图层属性的值。\n因为隐式动画使用默认的动画属性，所以显示动画比隐式动画更容易进行配置和管理。\n ----------------------\n文档引用：<官方文档-《Core Animation Programming Guide》-1-简介〉\n使用核心动画创建的大多数动画都涉及到图层属性的修改。与视图一样，图层对象也有一个bounds矩形、屏幕上的位置(position)、不透明度(opacity)、变换(transform)和许多其他可以修改的面向视觉的属性。对于这些属性中的大多数，改变属性的值会导致创建一个隐式动画，从而使图层从旧值动画到新值。\n官方文档-《Core Animation Programming Guide》-4-Animating Layer Content\n隐式动画使用默认的计时和动画属性来执行动画，而显式动画需要你自己使用动画对象来配置这些属性。\n与更新图层对象数据值的隐式动画不同，显式动画不会修改图层树中的数据。显式动画只产生动画。在动画结束时，Core animation从图层中移除动画对象，并使用其当前数据值重新绘制图层。";
    }
    if ([key isEqualToString:@"3-2"]) {
        answer = @"答：\n（1）UIView（基于图层的视图）的动画其实就是直接使用核心动画的接口来动画图层。只不过UIView类默认禁用图层动画，但在动画block中恢复了图层动画（UIView将actionForKey方法恢复了默认实现）。\n（2）Core Animation为许多UIKit视图属性中的动画变化提供了底层支持，也可以用来实现自定义动画。\n文档引用：\n1）有一些方法可以直接使用核心动画接口来动画图层。\n2）如果你想使用Core Animation类来初始化动画，你必须在基于视图的动画块中发出所有Core Animation调用。UIView类默认禁用图层动画，但在动画块中重新启用它们。\n3）Core Animation为许多UIKit视图属性中的动画变化提供了底层支持，也可以用来实现自定义动画。";
    }
    if ([key isEqualToString:@"4"]) {
        answer = @"答：CPU把提供的内容绘制并缓存到位图，提供给GPU。\n核心动画如何绘制内容：\n（1）图层捕获你的应用程序提供的内容并将其缓存到位图中。\n（2）当您随后更改图层的属性时，您所做的只是更改与图层对象相关的状态信息。当这个变化触发一个动画时，核心动画将图层的位图和状态信息传递给图形硬件（GPU）。\n（3）图形处理器（GPU）使用新的信息渲染到位图上；\n文档引用：官方文档-《Core Animation Programming Guide》-2-Core Animation Basics-1.1 基于层的绘图模型";
    }
    
    if ([key isEqualToString:@"5"]) {
        answer = @"1.图层的绘图分二种，\n（1）一种是基于动态的提供位图，通过创建图形上下文提供位图，和视图的绘图是一样的。\n例如：\na)通过图层代理方法绘制drawLayer: inContext:；\nb)通过定义一个图层子类并重写绘制方法drawInContext:；\n（2）另外一种是基于静态的提供位图，直接操作缓存位图，避免了CPU的重复绘制。\n例如：- (void)display直接把位图赋值给content。\n2.基于视图的绘图，对视图本身的更改通常会导致调用视图（UIKit）的drawRect:方法来使用新参数重新绘制内容。是基于动态位图的图层绘图（drawLayer:inContext:）的包装。这个绘制需要通过主线程上的CPU完成，所以这种方式绘制是昂贵的。而图层的绘图其中一种方式是静态的提供位图，直接操作缓存位图，避免了CPU的重复绘制的开销。- (void)display直接把位图赋值给content。\n 但是drawRect和动态位图的图层绘图（drawLayer:inContext:）又有区别，drawRect：做了性能优化，只绘制当前屏幕需要渲染的最小区域rect。\n文档引用：<官方文档-《Core Animation Programming Guide》-2-核心动画基础>\n1）因为它操作静态位图，基于图层的绘图与更传统的基于视图的绘图技术有很大的不同。对于基于视图的绘图，对视图本身的更改通常会导致调用视图的drawRect:方法来使用新参数重新绘制内容。但是以这种方式绘制是昂贵的，因为它是使用主线程上的CPU完成的。\n2）Core Animation通过尽可能操纵图形硬件(Graphics Hardware)中的缓存位图来实现相同或类似的效果，从而避免了这种开销。\n3）它是一种与视图集成的技术，以提供更好的性能和对其内容动画化的支持。它通过将视图的内容缓存到可由图形硬件(Graphics Hardware)直接操作的位图中来实现这种行为。";
    }
    if ([key isEqualToString:@"6"]) {
        answer = @"答：\n使用核心动画的应用程序有三组图层对象。\n1.模型图层存储的是图层的属性，对图层的属性进行设置就是改变模型层的数据。用于存储任何动画的目标值。\n2.表现图层代表屏幕上正在运行的动画的当前值。我们不能修改这个图层对象的属性，可以读取当前的动画值。（任何时候，我们都不应该手动地修改这个图层对象的属性，其属性的变化是由系统进行驱动的，可以通过这个对象获取在某一时刻页面上展现的图层的真实状态属性。）\n3.渲染图层执行实际的动画。\n\n动画是在渲染图层上执行的。\n\n文档引用：官方文档-《Core Animation Programming Guide》-2-Core Animation Basics-图层树反映了动画状态的不同方面\n使用核心动画的应用程序有三组图层对象。每一组图层对象都有不同的作用，使你的应用程序的内容出现在屏幕上:\n1.模型层树(或简称“图层树”)中的对象是应用程序与之交互最多的对象，用于存储任何动画的目标值。当你改变一个图层的属性时，你使用的始终是某一个模型对象。\n2.表现层树中的对象代表屏幕上正在运行的动画的当前值。永远不要修改此树中的对象。相反，您可以使用这些对象来读取当前的动画值，或者从这些值开始创建一个新的动画。\n3.渲染层树中的对象执行实际的动画，并且是Core Animation私有的。";
    }
    [anDic setValue:answer forKey:@"answer"];
    vc.dic = anDic;
    [self.navigationController pushViewController:vc animated:YES];

}
/*
#pragma mark - Navigation

// In a storyboard-based application, you will often want to do a little preparation before navigation
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
    // Get the new view controller using [segue destinationViewController].
    // Pass the selected object to the new view controller.
}
*/

@end
